#ifndef _XMESH_RATIONAL_H
#define _XMESH_RATIONAL_H

//namespace REAL
//{
enum OPERATOR {PLUS, MINUS, NEG, MUL, DIV, POWER, ROOT};

#define NUMBER double 
class DAGNode 
{
public: 
	DAGNode (): left (NULL), right(NULL), is_leaf (true)  {}
	DAGNode (const DAGNode &  obj)
	{
		this->left = obj.left ;
		this->right = obj.right ;
		this->is_leaf = obj.is_leaf ;
		this->op = obj.op ;
		this->number = obj.number ;
	}
public:

	OPERATOR op ; 
	NUMBER number ;

	DAGNode const * left ;
	DAGNode const * right ;
	bool is_leaf ;


	friend std::ostream & operator << (std::ostream & ostr, const DAGNode & obj)
	{		
		if (obj.is_leaf) 
		{
			ostr << obj.number <<' ';
		}
		else
		{
			switch (obj.op )
			{
			case PLUS : ostr <<'+' << ' '; break; 
			case MUL : ostr <<'*' << ' '; break; 
			case DIV : ostr <<'/' << ' '; break; 
			case MINUS : case NEG : ostr <<'-' << ' '; break; 	
			default:
				;
			}
		}
		if (obj.left != NULL) operator << (ostr,  * obj.left   ) ;
		if (obj.right != NULL) operator << (ostr,  * obj.right ) ;

		return ostr ; 
	}
};

class Real
{
public:
	Real () 
	{
	}
    Real(NUMBER num) 
	{
		this->m_dag_node.number = num; 
	}

	Real (const Real & obj)
	{
		this->m_dag_node = obj.m_dag_node ;
	}
	friend Real operator + (const Real & lhs, const Real & rhs)
	{
		Real plus_node ; 
		plus_node.m_dag_node.is_leaf = false ;
		plus_node.m_dag_node.op = PLUS ;
		plus_node.m_dag_node.left = & lhs.m_dag_node ;
		plus_node.m_dag_node.right =  & rhs.m_dag_node ;
		return plus_node ;
	}
	/**
	 * Overload negative
	 */
	friend Real operator - (const Real & ops)
	{
		Real plus_node ; 
		plus_node.m_dag_node.is_leaf = false ;
		plus_node.m_dag_node.op = NEG ;
		plus_node.m_dag_node.left = & ops.m_dag_node ;
		plus_node.m_dag_node.right =  NULL ;
		return plus_node ;
	}

	/**
	 * Overload minus
	 */
	friend Real operator - (const Real & lhs, const Real & rhs)
	{
		Real plus_node ; 
		plus_node.m_dag_node.is_leaf = false ;
		plus_node.m_dag_node.op = MINUS ;
		plus_node.m_dag_node.left = & lhs.m_dag_node ;
		plus_node.m_dag_node.right =  & rhs.m_dag_node ;
		return plus_node ;
	}

	friend Real operator * (const Real & lhs, const Real & rhs)
	{
		Real node ; 
		node.m_dag_node.is_leaf = false ;
		node.m_dag_node.op = MUL ;
		node.m_dag_node.left = & lhs.m_dag_node ;
		node.m_dag_node.right =  & rhs.m_dag_node ;
		return node ;
	}

	friend Real operator / (const Real & lhs, const Real & rhs)
	{
		Real node ; 
		node.m_dag_node.is_leaf = false ;
		node.m_dag_node.op = DIV ;
		node.m_dag_node.left = & lhs.m_dag_node ;
		node.m_dag_node.right =  & rhs.m_dag_node ;
		return node ;
	}

	friend std::ostream & operator << (std::ostream & ostr, const Real & obj)
	{		
		ostr<< obj.m_dag_node ;
		return ostr ;
	}
private: 
	DAGNode m_dag_node; 
};

//};
#endif
